package ywh.utils.scorm {
	import flash.external.*;

	public class AS3_SCORM_Wrapper implements IScormAPI {
		private var __connectionActive:Boolean = false, __debugActive:Boolean = true;

		public function AS3_SCORM_Wrapper() {
			var is_EI_available : Boolean = ExternalInterface.available, wrapperFound : Boolean = false, debugMsg : String = "Initializing SCORM class. Checking dependencies: ";

			if (is_EI_available) {
				debugMsg += "ExternalInterface.available evaluates true. ";

				wrapperFound = Boolean(ExternalInterface.call("williwhyang.SCORM.isAvailable"));
				debugMsg += "SCORM.isAvailable() evaluates " + String(wrapperFound) + ". ";

				if (wrapperFound) {
					debugMsg += "SCORM class file ready to go!  :) ";
				} else {
					debugMsg += "The required JavaScript SCORM API wrapper cannot be found in the HTML document.  Course cannot load.";
				}
			} else {
				debugMsg += "ExternalInterface is NOT available (this may be due to an outdated version of Flash Player).  Course cannot load.";
			}

			__displayDebugInfo(debugMsg);
		}

		// --- public functions --------------------------------------------- //
		public function set debugMode(status : Boolean) : void {
			this.__debugActive = status;
		}

		public function get debugMode() : Boolean {
			return this.__debugActive;
		}

		public function connect() : Boolean {
			__displayDebugInfo("williwhyang.SCORM.connect() called from class file");
			return __connect();
		}

		public function disconnect() : Boolean {
			return __disconnect();
		}

		public function getValue(param : String) : String {
			var str : String = __get(param);
			__displayDebugInfo("public function get returned: " + str);
			return str;
		}

		public function setValue(parameter : String, value : String) : Boolean {
			return __set(parameter, value);
		}

		public function save() : Boolean {
			return __save();
		}

		// --- private functions --------------------------------------------- //
		private function __connect() : Boolean {
			var result : Boolean = false;
			if (!__connectionActive) {
				var eiCall : String = String(ExternalInterface.call("williwhyang.SCORM.init"));
				result = __stringToBoolean(eiCall);

				if (result) {
					__connectionActive = true;
				} else {
					var errorCode : int = __getDebugCode();
					if (errorCode) {
						var debugInfo : String = __getDebugInfo(errorCode);
						__displayDebugInfo("williwhyang.SCORM.init() failed. \n" + "Error code: " + errorCode + "\n" + "Error info: " + debugInfo);
					} else {
						__displayDebugInfo("williwhyang.SCORM.init failed: no response from server.");
					}
				}
			} else {
				__displayDebugInfo("williwhyang.SCORM.init aborted: connection already active.");
			}

			__displayDebugInfo("__connectionActive: " + __connectionActive);

			return result;
		}

		private function __disconnect() : Boolean {
			var result : Boolean = false;
			if (__connectionActive) {
				var eiCall : String = String(ExternalInterface.call("williwhyang.SCORM.quit"));
				result = __stringToBoolean(eiCall);
				if (result) {
					__connectionActive = false;
				} else {
					var errorCode : int = __getDebugCode();
					var debugInfo : String = __getDebugInfo(errorCode);
					__displayDebugInfo("williwhyang.SCORM.quit() failed. \n" + "Error code: " + errorCode + "\n" + "Error info: " + debugInfo);
				}
			} else {
				__displayDebugInfo("williwhyang.SCORM.quit aborted: connection already inactive.");
			}
			return result;
		}

		private function __get(parameter : String) : String {
			var returnedValue : String = "";

			if (__connectionActive) {
				returnedValue = String(ExternalInterface.call("williwhyang.SCORM.get", parameter));
				var errorCode : int = __getDebugCode();

				if (returnedValue == "" && errorCode != 0) {
					var debugInfo : String = __getDebugInfo(errorCode);
					__displayDebugInfo("williwhyang.SCORM.get(" + parameter + ") failed. \n" + "Error code: " + errorCode + "\n" + "Error info: " + debugInfo);
				}
			} else {
				__displayDebugInfo("williwhyang.SCORM.get(" + parameter + ") failed: connection is inactive.");
			}
			return returnedValue;
		}

		private function __set(parameter : String, value : String) : Boolean {
			var result : Boolean = false;
			if (__connectionActive) {
				var eiCall : String = String(ExternalInterface.call("williwhyang.SCORM.set", parameter, value));
				result = __stringToBoolean(eiCall);
				if (!result) {
					var errorCode : int = __getDebugCode();
					var debugInfo : String = __getDebugInfo(errorCode);
					__displayDebugInfo("williwhyang.SCORM.set(" + parameter + ") failed. \n" + "Error code: " + errorCode + "\n" + "Error info: " + debugInfo);
				}
			} else {
				__displayDebugInfo("williwhyang.SCORM.set(" + parameter + ") failed: connection is inactive.");
			}
			return result;
		}

		private function __save() : Boolean {
			var result : Boolean = false;
			if (__connectionActive) {
				var eiCall : String = String(ExternalInterface.call("williwhyang.SCORM.save"));
				result = __stringToBoolean(eiCall);
				if (!result) {
					var errorCode : int = __getDebugCode();
					var debugInfo : String = __getDebugInfo(errorCode);
					__displayDebugInfo("williwhyang.SCORM.save() failed. \n" + "Error code: " + errorCode + "\n" + "Error info: " + debugInfo);
				}
			} else {
				__displayDebugInfo("williwhyang.SCORM.save() failed: API connection is inactive.");
			}
			return result;
		}

		// --- debug functions ----------------------------------------------- //
		private function __getDebugCode() : int {
			var code : int = int(ExternalInterface.call("williwhyang.SCORM.debug.getCode"));
			return code;
		}

		private function __getDebugInfo(errorCode : int) : String {
			var result : String = String(ExternalInterface.call("williwhyang.SCORM.debug.getInfo", errorCode));
			return result;
		}

//		private function __getDiagnosticInfo(errorCode : int) : String {
//			var result : String = String(ExternalInterface.call("williwhyang.SCORM.debug.getDiagnosticInfo", errorCode));
//			return result;
//		}

		private function __displayDebugInfo(msg : String) : void {
			if (__debugActive) {
				// trace(msg);
				ExternalInterface.call("williwhyang.UTILS.trace", msg);
			}
		}

		private function __stringToBoolean(string : String) : Boolean {
			if (string != null) {
				switch (string.toLowerCase()) {
					case "true":
					case "yes":
					case "1":
						return true;
					case "false":
					case "no":
					case "0":
						return false;
				}
			}
			return false;
		}
	}
}